package frame;

import util.TextEditorUtil;

import javax.swing.*;
import java.io.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static util.TranslateUtil.translate;

public class TranslateWorker extends SwingWorker<Void, String> {
	private final MainFrame mainFrame;
	private File rootFile;

	// 匹配位于行首的注释中的Doc注释，去掉前面的 *
	public static final Pattern TOP_OF_LINE = Pattern.compile("^\\s*@\\S+\\s+(.+)");
	// 文本中的Doc注释
	public static final Pattern DOC_IN_ANNO = Pattern.compile("\\{@\\S+\\s+.+?\\}");
	// 文本中的方法
	public static final Pattern METHOD_IN_ANNO = Pattern.compile(" (\\S+\\(\\)) ");
	public static final Pattern LINE = Pattern.compile("^\\s*\\*");

	public TranslateWorker(MainFrame mainFrame, File rootFile) {
		this.mainFrame = mainFrame;
		this.rootFile = rootFile;
	}

	@Override
	protected Void doInBackground() throws Exception {
		// 拷贝一份作为备份
		File newFile = renameOldFile();
		copyFile(rootFile, newFile);

		// 操作源文件
		if (rootFile.isFile()) {
			processFile(rootFile);
		} else {
			processDir(rootFile);
		}

		return null;
	}

	private void copyFile(File oldFile, File newFile) {
		if (oldFile.isFile()) {
			// 拷贝文件
			try (BufferedWriter bw = new BufferedWriter(new FileWriter(newFile));
			     BufferedReader br = new BufferedReader(new FileReader(oldFile))) {
				String line;
				while ((line = br.readLine()) != null) bw.write(line + "\n");
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		} else {
			// 目录
			File[] files = oldFile.listFiles(pathname -> pathname.isDirectory() || pathname.getName().endsWith(".java"));
			if (files == null) return;

			for (File file : files) {
				File f = new File(newFile + File.separator + file.getName());
				// 创建目录
				if (file.isDirectory()) f.mkdirs();
				copyFile(file, f);
			}
		}
	}

	// 返回新的文件名
	private File renameOldFile() {
		String rootName = rootFile.getName();
		int id = 0;
		File f;
		do {
			if (rootFile.isFile()) {
				f = new File(rootFile.getParent() + File.separator + rootName.substring(0, rootName.lastIndexOf(".")) + (id == 0 ? "" : id) + "old.java");
			} else {
				f = new File(rootFile.getParent() + File.separator + rootName + (id == 0 ? "" : id) + "old");
			}
			id++;
		} while (f.exists());

		return f;
	}

	@Override
	protected void process(List<String> chunks) {
		for (String s : chunks) {
			TextEditorUtil.appendAtEnd(mainFrame.getLogPane(), s);
		}
	}

	/** 递归处理文件 */
	private void processDir(File dir) {
		File[] files = dir.listFiles(pathname -> pathname.isDirectory() || pathname.getName().endsWith(".java"));
		if (files == null) return;
		for (File file : files) {
			if (file.isFile()) {
				// java文件
				processFile(file);
			} else {
				// 目录
				processDir(file);
			}
		}
	}

	/** 处理每个java文件 */
	private void processFile(File f) {
		StringBuilder builder = new StringBuilder();

		try (BufferedReader br = new BufferedReader(new FileReader(f))) {
			String line;

			while ((line = br.readLine()) != null) {
				int start = line.indexOf("/**");
				int end = line.indexOf("*/");

				if (start != -1 && end != -1) {
					// 只有一行的注释
					line = "/**" + processDocInAnno(line.substring(start + 3, end)) + " */";
					builder.append(line).append("\n");
				} else if (start != -1) {
					// 注释的第一行


				} else if (end != -1) {
					// 注释的最后一行

				} else {
					// 不是注释
				}
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		// 写入
		try (BufferedWriter bw = new BufferedWriter(new FileWriter(f))) {
			bw.write(builder.toString());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		publish(f.getAbsolutePath() + " 文件翻译完毕");
	}

	/** 处理给定文本中的行内Doc标签 */
	private static String processDocInAnno(String s) {
		StringBuilder content;
		Matcher matcher = DOC_IN_ANNO.matcher(s);
		if (matcher.find()) {
			// 含有行内doc
			content = new StringBuilder(translate(s.substring(0, matcher.start())) + matcher.group());
			int e = matcher.end();
			while (matcher.find()) {
				content.append(translate(s.substring(e, matcher.start()))).append(matcher.group());
				e = matcher.end();
			}
			content.append(translate(s.substring(e)));
			return content.toString();
		} else {
			return translate(s);
		}
	}

	/** 处理文本中未使用标签包含的方法，需特殊处理防止被翻译 */
	private static String processMethod(String s) {
		StringBuilder content;
		Matcher matcher = METHOD_IN_ANNO.matcher(s);
		if (matcher.find()) {
			// 含有行内doc
			content = new StringBuilder(translate(s.substring(0, matcher.start())) + matcher.group());
			int e = matcher.end();
			while (matcher.find()) {
				content.append(translate(s.substring(e, matcher.start()))).append(matcher.group());
				e = matcher.end();
			}
			content.append(translate(s.substring(e)));
			return content.toString();
		} else {
			return translate(s);
		}
	}

	@Override
	protected void done() {
		mainFrame.getTranslateButton().setEnabled(true);
		JOptionPane.showConfirmDialog(mainFrame, "所有注释翻译完成", "成功", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
	}
}
